Hedging Renewable Energy Investments with Bitcoin Mining

Authors: Bastian-Pinto, C., Araujo, F. VdS., Brandão, L. E. T., Gomes, L. L.

Abstract Renewable energy sources such as wind power are increasing their share of the world energy matrix. Nonetheless, wind farms projects are subject to variations in output due to climate conditions and to price volatility if they choose to anticipate construction to sell their energy in the short term markets. In order to create incentives for early investment, we show that wind farm investors can hedge electricity price risk by simultaneously investing in a cryptocurrency mining facility that uses electricity as input to produce newly minted Bitcoins to sell in the market. Given that electricity and Bitcoin prices are mostly uncorrelated, the ability to switch outputs between these two assets depending on their relative prices, allows the firm to maximize revenues and minimize losses. We develop a numerical application where we apply the real options approach to model a wind farm that chooses to anticipate construction in order to sell energy in the short term market for up to four years prior to entering into its long term energy sales commitment. Given that this power plant also invests in a Bitcoin mining facility, whenever the price of the Bitcoins created is higher than the market price of electric power, the firm will choose to operate the mining facility. Otherwise, it will sell its energy to the market. The short-term energy price and Bitcoin price/mining-difficulty ratio are modeled as two distinct stochastic diffusion processes. The results show that the option to switch outputs significantly increases the generator’s revenue while simultaneously decreasing the risk.

Keywords: real options, switch option, renewable energy production, cryptocurrency mining, bit-spread

This page presents the analysis of the Bitcoin Price/Difficulty construct used in the paper. All the code was run in RStudio using the version of the software below.

Software version

R.version
               _                           
platform       x86_64-w64-mingw32          
arch           x86_64                      
os             mingw32                     
system         x86_64, mingw32             
status                                     
major          4                           
minor          0.1                         
year           2020                        
month          06                          
day            06                          
svn rev        78648                       
language       R                           
version.string R version 4.0.1 (2020-06-06)
nickname       See Things Now              

Setting of the environment

# Global Chart Configurations
# Used to resize plots
require(repr) 
Loading required package: repr
package 㤼㸱repr㤼㸲 was built under R version 4.0.2Registered S3 methods overwritten by 'htmltools':
  method               from         
  print.html           tools:rstudio
  print.shiny.tag      tools:rstudio
  print.shiny.tag.list tools:rstudio
options(repr.plot.width=8, repr.plot.height=3) 
# Used to print tables inside the R Notebook
require(knitr)
Loading required package: knitr

Loading Data

Read data from ‘Data’ folder in project structure. Data comes without headers so col.names are added. Column classes are defined since data format is previously known.

Price Data

original.data = read.csv(file='../Data/market-price.csv', col.names=c('Date', 'Price'), colClasses=c('character', 'double'))

# Backup for verification purposes
price.data = original.data 

# Adjust dates
price.data$Date = as.Date(price.data$Date, format="%m/%d/%Y")

# Show the first six lines of data
kable(head(price.data), caption="First lines of imported Price data:")
First lines of imported Price data:
Date Price
2014-08-25 502.93
2014-08-26 512.56
2014-08-27 515.23
2014-08-28 510.75
2014-08-29 512.56
2014-08-30 505.96

Difficulty Data

difficulty.data = read.csv(file='../Data/difficulty.csv', col.names=c('Date', 'Difficulty'), colClasses=c('Date', 'double'))

# Show the first six lines of data
kable(head(difficulty.data), caption="First lines of imported Difficulty data:")
First lines of imported Difficulty data:
Date Difficulty
2009-01-06 0
2009-01-09 1
2009-01-12 1
2009-01-15 1
2009-01-18 1
2009-01-21 1

Calculating the returns

# Obtain log of prices
price.data$LogPrice <- log(price.data$Price)

# Calculate returns
# Use NA in the first position of the vector since diff return has one less observation
price.data$Returns <- c(NA, diff(price.data$LogPrice)) 

Selecting a subset of the data

selected.price.data <- price.data[which(price.data$Date=="2015-02-01"):nrow(price.data), ]

selected.difficulty.data <- difficulty.data[which(difficulty.data$Date=="2015-02-01"):nrow(difficulty.data), ]

selected.data <- merge(selected.price.data, selected.difficulty.data, by="Date")

# Display the number of rows (data points)
paste("There are", nrow(selected.price.data), "Price data points and", nrow(selected.difficulty.data), "Difficulty data points. The merged database have the following number of data points:", nrow(selected.data))
[1] "There are 1633 Price data points and 582 Difficulty data points. The merged database have the following number of data points: 582"

Calculate Price/Difficulty Series

selected.data$Price_Difficulty <- selected.data$Price * 10^8 / selected.data$Difficulty

# Display the six first and last rows of the data set
kable(head(selected.data), caption="Display the six first rows of the data set")

Display the six first rows of the data set
Date Price LogPrice Returns Difficulty Price_Difficulty
2015-02-01 225.29 5.417389 0.0305567 41272873895 0.5458549
2015-02-04 226.58 5.423098 -0.0036565 41272873895 0.5489804
2015-02-07 227.68 5.427941 0.0209488 41272873895 0.5516456
2015-02-10 219.67 5.392126 -0.0030454 44455415962 0.4941355
2015-02-13 236.17 5.464552 0.0628209 44455415962 0.5312514
2015-02-16 235.83 5.463111 0.0109146 44455415962 0.5304865

kable(tail(selected.data), caption="Display the six last rows of the data set")
Display the six last rows of the data set
Date Price LogPrice Returns Difficulty Price_Difficulty
577 2019-10-26 9292.025 9.136912 0.1670331 1.369148e+13 0.0678672
578 2019-10-29 9385.600 9.146932 -0.0088943 1.369148e+13 0.0685507
579 2019-11-01 9147.238 9.121207 -0.0035710 1.369148e+13 0.0668097
580 2019-11-04 9266.701 9.134183 0.0053030 1.369148e+13 0.0676822
581 2019-11-07 9241.038 9.131410 -0.0094475 1.366989e+13 0.0676014
582 2019-11-10 8896.403 9.093402 0.0098398 1.272001e+13 0.0699402

Plot Series

plot(Price_Difficulty ~ Date, selected.data, xaxt = "n", type = "l"); axis(1, selected.data$Date, format(selected.data$Date, "%b %Y"), cex.axis = .7)

LS0tDQp0aXRsZTogIk1vbnRlIENhcmxvIFNpbXVsYXRpb24iDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQojIyAgSGVkZ2luZyBSZW5ld2FibGUgRW5lcmd5IEludmVzdG1lbnRzIHdpdGggQml0Y29pbiBNaW5pbmcNCg0KQXV0aG9yczogQmFzdGlhbi1QaW50bywgQy4sIEFyYXVqbywgRi4gVmRTLiwgQnJhbmTDo28sIEwuIEUuIFQuLCBHb21lcywgTC4gTC4NCg0KQWJzdHJhY3QgUmVuZXdhYmxlIGVuZXJneSBzb3VyY2VzIHN1Y2ggYXMgd2luZCBwb3dlciBhcmUgaW5jcmVhc2luZyB0aGVpciBzaGFyZSBvZiB0aGUgd29ybGQgZW5lcmd5IG1hdHJpeC4gTm9uZXRoZWxlc3MsIHdpbmQgZmFybXMgcHJvamVjdHMgYXJlIHN1YmplY3QgdG8gdmFyaWF0aW9ucyBpbiBvdXRwdXQgZHVlIHRvIGNsaW1hdGUgY29uZGl0aW9ucyBhbmQgdG8gcHJpY2Ugdm9sYXRpbGl0eSBpZiB0aGV5IGNob29zZSB0byBhbnRpY2lwYXRlIGNvbnN0cnVjdGlvbiB0byBzZWxsIHRoZWlyIGVuZXJneSBpbiB0aGUgc2hvcnQgdGVybSBtYXJrZXRzLiBJbiBvcmRlciB0byBjcmVhdGUgaW5jZW50aXZlcyBmb3IgZWFybHkgaW52ZXN0bWVudCwgd2Ugc2hvdyB0aGF0IHdpbmQgZmFybSBpbnZlc3RvcnMgY2FuIGhlZGdlIGVsZWN0cmljaXR5IHByaWNlIHJpc2sgYnkgc2ltdWx0YW5lb3VzbHkgaW52ZXN0aW5nIGluIGEgY3J5cHRvY3VycmVuY3kgbWluaW5nIGZhY2lsaXR5IHRoYXQgdXNlcyBlbGVjdHJpY2l0eSBhcyBpbnB1dCB0byBwcm9kdWNlIG5ld2x5IG1pbnRlZCBCaXRjb2lucyB0byBzZWxsIGluIHRoZSBtYXJrZXQuIEdpdmVuIHRoYXQgZWxlY3RyaWNpdHkgYW5kIEJpdGNvaW4gcHJpY2VzIGFyZSBtb3N0bHkgdW5jb3JyZWxhdGVkLCB0aGUgYWJpbGl0eSB0byBzd2l0Y2ggb3V0cHV0cyBiZXR3ZWVuIHRoZXNlIHR3byBhc3NldHMgZGVwZW5kaW5nIG9uIHRoZWlyIHJlbGF0aXZlIHByaWNlcywgYWxsb3dzIHRoZSBmaXJtIHRvIG1heGltaXplIHJldmVudWVzIGFuZCBtaW5pbWl6ZSBsb3NzZXMuIFdlIGRldmVsb3AgYSBudW1lcmljYWwgYXBwbGljYXRpb24gd2hlcmUgd2UgYXBwbHkgdGhlIHJlYWwgb3B0aW9ucyBhcHByb2FjaCB0byBtb2RlbCBhIHdpbmQgZmFybSB0aGF0IGNob29zZXMgdG8gYW50aWNpcGF0ZSBjb25zdHJ1Y3Rpb24gaW4gb3JkZXIgdG8gc2VsbCBlbmVyZ3kgaW4gdGhlIHNob3J0IHRlcm0gbWFya2V0IGZvciB1cCB0byBmb3VyIHllYXJzIHByaW9yIHRvIGVudGVyaW5nIGludG8gaXRzIGxvbmcgdGVybSBlbmVyZ3kgc2FsZXMgY29tbWl0bWVudC4gR2l2ZW4gdGhhdCB0aGlzIHBvd2VyIHBsYW50IGFsc28gaW52ZXN0cyBpbiBhIEJpdGNvaW4gbWluaW5nIGZhY2lsaXR5LCB3aGVuZXZlciB0aGUgcHJpY2Ugb2YgdGhlIEJpdGNvaW5zIGNyZWF0ZWQgaXMgaGlnaGVyIHRoYW4gdGhlIG1hcmtldCBwcmljZSBvZiBlbGVjdHJpYyBwb3dlciwgdGhlIGZpcm0gd2lsbCBjaG9vc2UgdG8gb3BlcmF0ZSB0aGUgbWluaW5nIGZhY2lsaXR5LiBPdGhlcndpc2UsIGl0IHdpbGwgc2VsbCBpdHMgZW5lcmd5IHRvIHRoZSBtYXJrZXQuIFRoZSBzaG9ydC10ZXJtIGVuZXJneSBwcmljZSBhbmQgQml0Y29pbiBwcmljZS9taW5pbmctZGlmZmljdWx0eSByYXRpbyBhcmUgbW9kZWxlZCBhcyB0d28gZGlzdGluY3Qgc3RvY2hhc3RpYyBkaWZmdXNpb24gcHJvY2Vzc2VzLiBUaGUgcmVzdWx0cyBzaG93IHRoYXQgdGhlIG9wdGlvbiB0byBzd2l0Y2ggb3V0cHV0cyBzaWduaWZpY2FudGx5IGluY3JlYXNlcyB0aGUgZ2VuZXJhdG9y4oCZcyByZXZlbnVlIHdoaWxlIHNpbXVsdGFuZW91c2x5IGRlY3JlYXNpbmcgdGhlIHJpc2suDQoNCktleXdvcmRzOiByZWFsIG9wdGlvbnMsIHN3aXRjaCBvcHRpb24sIHJlbmV3YWJsZSBlbmVyZ3kgcHJvZHVjdGlvbiwgY3J5cHRvY3VycmVuY3kgbWluaW5nLCBiaXQtc3ByZWFkDQoNClRoaXMgcGFnZSBwcmVzZW50cyB0aGUgYW5hbHlzaXMgb2YgdGhlIEJpdGNvaW4gUHJpY2UvRGlmZmljdWx0eSBjb25zdHJ1Y3QgdXNlZCBpbiB0aGUgcGFwZXIuIEFsbCB0aGUgY29kZSB3YXMgcnVuIGluIFJTdHVkaW8gdXNpbmcgdGhlIHZlcnNpb24gb2YgdGhlIHNvZnR3YXJlIGJlbG93Lg0KDQojIyMgU29mdHdhcmUgdmVyc2lvbg0KDQpgYGB7cn0NClIudmVyc2lvbg0KYGBgDQoNCiMjIyBTZXR0aW5nIG9mIHRoZSBlbnZpcm9ubWVudA0KDQpgYGB7cn0NCiMgR2xvYmFsIENoYXJ0IENvbmZpZ3VyYXRpb25zDQojIFVzZWQgdG8gcmVzaXplIHBsb3RzDQpyZXF1aXJlKHJlcHIpIA0Kb3B0aW9ucyhyZXByLnBsb3Qud2lkdGg9OCwgcmVwci5wbG90LmhlaWdodD0zKSANCiMgVXNlZCB0byBwcmludCB0YWJsZXMgaW5zaWRlIHRoZSBSIE5vdGVib29rDQpyZXF1aXJlKGtuaXRyKQ0KYGBgDQoNCg0KIyMjIExvYWRpbmcgRGF0YQ0KDQpSZWFkIGRhdGEgZnJvbSAnRGF0YScgZm9sZGVyIGluIHByb2plY3Qgc3RydWN0dXJlLiBEYXRhIGNvbWVzIHdpdGhvdXQgaGVhZGVycyBzbyBjb2wubmFtZXMgYXJlIGFkZGVkLiBDb2x1bW4gY2xhc3NlcyBhcmUgZGVmaW5lZCBzaW5jZSBkYXRhIGZvcm1hdCBpcyBwcmV2aW91c2x5IGtub3duLg0KDQojIyMjIFByaWNlIERhdGENCmBgYHtyfQ0Kb3JpZ2luYWwuZGF0YSA9IHJlYWQuY3N2KGZpbGU9Jy4uL0RhdGEvbWFya2V0LXByaWNlLmNzdicsIGNvbC5uYW1lcz1jKCdEYXRlJywgJ1ByaWNlJyksIGNvbENsYXNzZXM9YygnY2hhcmFjdGVyJywgJ2RvdWJsZScpKQ0KDQojIEJhY2t1cCBmb3IgdmVyaWZpY2F0aW9uIHB1cnBvc2VzDQpwcmljZS5kYXRhID0gb3JpZ2luYWwuZGF0YSANCg0KIyBBZGp1c3QgZGF0ZXMNCnByaWNlLmRhdGEkRGF0ZSA9IGFzLkRhdGUocHJpY2UuZGF0YSREYXRlLCBmb3JtYXQ9IiVtLyVkLyVZIikNCg0KIyBTaG93IHRoZSBmaXJzdCBzaXggbGluZXMgb2YgZGF0YQ0Ka2FibGUoaGVhZChwcmljZS5kYXRhKSwgY2FwdGlvbj0iRmlyc3QgbGluZXMgb2YgaW1wb3J0ZWQgUHJpY2UgZGF0YToiKQ0KYGBgDQoNCg0KIyMjIyBEaWZmaWN1bHR5IERhdGENCmBgYHtyfQ0KZGlmZmljdWx0eS5kYXRhID0gcmVhZC5jc3YoZmlsZT0nLi4vRGF0YS9kaWZmaWN1bHR5LmNzdicsIGNvbC5uYW1lcz1jKCdEYXRlJywgJ0RpZmZpY3VsdHknKSwgY29sQ2xhc3Nlcz1jKCdEYXRlJywgJ2RvdWJsZScpKQ0KDQojIFNob3cgdGhlIGZpcnN0IHNpeCBsaW5lcyBvZiBkYXRhDQprYWJsZShoZWFkKGRpZmZpY3VsdHkuZGF0YSksIGNhcHRpb249IkZpcnN0IGxpbmVzIG9mIGltcG9ydGVkIERpZmZpY3VsdHkgZGF0YToiKQ0KYGBgDQoNCg0KIyMjIENhbGN1bGF0aW5nIHRoZSByZXR1cm5zDQoNCmBgYHtyfQ0KIyBPYnRhaW4gbG9nIG9mIHByaWNlcw0KcHJpY2UuZGF0YSRMb2dQcmljZSA8LSBsb2cocHJpY2UuZGF0YSRQcmljZSkNCg0KIyBDYWxjdWxhdGUgcmV0dXJucw0KIyBVc2UgTkEgaW4gdGhlIGZpcnN0IHBvc2l0aW9uIG9mIHRoZSB2ZWN0b3Igc2luY2UgZGlmZiByZXR1cm4gaGFzIG9uZSBsZXNzIG9ic2VydmF0aW9uDQpwcmljZS5kYXRhJFJldHVybnMgPC0gYyhOQSwgZGlmZihwcmljZS5kYXRhJExvZ1ByaWNlKSkgDQpgYGANCg0KDQojIyMgU2VsZWN0aW5nIGEgc3Vic2V0IG9mIHRoZSBkYXRhIA0KDQpgYGB7cn0NCnNlbGVjdGVkLnByaWNlLmRhdGEgPC0gcHJpY2UuZGF0YVt3aGljaChwcmljZS5kYXRhJERhdGU9PSIyMDE1LTAyLTAxIik6bnJvdyhwcmljZS5kYXRhKSwgXQ0KDQpzZWxlY3RlZC5kaWZmaWN1bHR5LmRhdGEgPC0gZGlmZmljdWx0eS5kYXRhW3doaWNoKGRpZmZpY3VsdHkuZGF0YSREYXRlPT0iMjAxNS0wMi0wMSIpOm5yb3coZGlmZmljdWx0eS5kYXRhKSwgXQ0KDQpzZWxlY3RlZC5kYXRhIDwtIG1lcmdlKHNlbGVjdGVkLnByaWNlLmRhdGEsIHNlbGVjdGVkLmRpZmZpY3VsdHkuZGF0YSwgYnk9IkRhdGUiKQ0KDQojIERpc3BsYXkgdGhlIG51bWJlciBvZiByb3dzIChkYXRhIHBvaW50cykNCnBhc3RlKCJUaGVyZSBhcmUiLCBucm93KHNlbGVjdGVkLnByaWNlLmRhdGEpLCAiUHJpY2UgZGF0YSBwb2ludHMgYW5kIiwgbnJvdyhzZWxlY3RlZC5kaWZmaWN1bHR5LmRhdGEpLCAiRGlmZmljdWx0eSBkYXRhIHBvaW50cy4gVGhlIG1lcmdlZCBkYXRhYmFzZSBoYXZlIHRoZSBmb2xsb3dpbmcgbnVtYmVyIG9mIGRhdGEgcG9pbnRzOiIsIG5yb3coc2VsZWN0ZWQuZGF0YSkpDQpgYGANCg0KIyMjIENhbGN1bGF0ZSBQcmljZS9EaWZmaWN1bHR5IFNlcmllcw0KDQpgYGB7cn0NCnNlbGVjdGVkLmRhdGEkUHJpY2VfRGlmZmljdWx0eSA8LSBzZWxlY3RlZC5kYXRhJFByaWNlICogMTBeOCAvIHNlbGVjdGVkLmRhdGEkRGlmZmljdWx0eQ0KDQojIERpc3BsYXkgdGhlIHNpeCBmaXJzdCBhbmQgbGFzdCByb3dzIG9mIHRoZSBkYXRhIHNldA0Ka2FibGUoaGVhZChzZWxlY3RlZC5kYXRhKSwgY2FwdGlvbj0iRGlzcGxheSB0aGUgc2l4IGZpcnN0IHJvd3Mgb2YgdGhlIGRhdGEgc2V0IikNCmthYmxlKHRhaWwoc2VsZWN0ZWQuZGF0YSksIGNhcHRpb249IkRpc3BsYXkgdGhlIHNpeCBsYXN0IHJvd3Mgb2YgdGhlIGRhdGEgc2V0IikNCmBgYA0KDQojIyMgUGxvdCBTZXJpZXMNCg0KYGBge3J9DQpwbG90KFByaWNlX0RpZmZpY3VsdHkgfiBEYXRlLCBzZWxlY3RlZC5kYXRhLCB4YXh0ID0gIm4iLCB0eXBlID0gImwiKTsgYXhpcygxLCBzZWxlY3RlZC5kYXRhJERhdGUsIGZvcm1hdChzZWxlY3RlZC5kYXRhJERhdGUsICIlYiAlWSIpLCBjZXguYXhpcyA9IC43KQ0KYGBgDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg==